package com.oj.judge.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.ObjectMapper;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.oj.api.domain.UserExeResult;
import com.oj.api.domain.dto.JudgeSubmitDTO;
import com.oj.api.domain.vo.UserQuestionResultVO;
import com.oj.common.core.constants.Constants;
import com.oj.common.core.constants.JudgeConstants;
import com.oj.common.core.enums.CodeRunStatus;
import com.oj.judge.domain.SandBoxExecuteResult;
import com.oj.judge.domain.UserSubmit;
import com.oj.judge.mapper.UserSubmitMapper;
import com.oj.judge.service.IJudgeService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description
 * @Author bin
 * @Date 2025/6/30
 */

@Service
public class JudgeServiceImpl implements IJudgeService {

    @Resource
    private UserSubmitMapper userSubmitMapper;

    @Resource
    private SandboxPoolServiceImpl sandboxPoolService;

    @Override
    public UserQuestionResultVO doJudgeJavaCode(JudgeSubmitDTO judgeSubmitDTO) {
        List<String> inputList = judgeSubmitDTO.getInputList();
        SandBoxExecuteResult sandBoxExecuteResult =
                sandboxPoolService.exeJavaCode(judgeSubmitDTO.getUserId(), judgeSubmitDTO.getUserCode(), inputList);
        UserQuestionResultVO userQuestionResultVO = new UserQuestionResultVO();
        if (sandBoxExecuteResult != null && CodeRunStatus.SUCCEED.equals(sandBoxExecuteResult.getRunStatus())) {
            // 比对期望输出和实际输出
            userQuestionResultVO = doJudgeRun(judgeSubmitDTO, sandBoxExecuteResult, inputList);
            System.out.println(sandBoxExecuteResult.getRunStatus());
        } else {
            userQuestionResultVO.setPass(Constants.FALSE);
            if (sandBoxExecuteResult != null) {
                userQuestionResultVO.setExeMessage(sandBoxExecuteResult.getExeMessage());
            } else {
                // 未知异常
                userQuestionResultVO.setExeMessage(CodeRunStatus.UNKNOWN_FAILED.getMsg());
            }
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
        }
        System.out.println("准备save答题记录");
        saveUserSubmit(judgeSubmitDTO, userQuestionResultVO);
        System.out.println("save完成");
        System.out.println(userQuestionResultVO.getPass());
        return userQuestionResultVO;
    }

    private static UserQuestionResultVO doJudgeRun(JudgeSubmitDTO judgeSubmitDTO, SandBoxExecuteResult sandBoxExecuteResult, List<String> inputList) {
        List<String> exeOutputList = sandBoxExecuteResult.getOutputList();
        List<String> expOutputList = judgeSubmitDTO.getOutputList();

        if (expOutputList.size() != exeOutputList.size()) {

            return UserQuestionResultVO.fail(Constants.FALSE, JudgeConstants.ERROR_ANSWER, null, JudgeConstants.ERROR_SCORE);

        }
        List<UserExeResult> userExeResultList = new ArrayList<>();

        for (int i = 0; i < expOutputList.size(); i++) {
            UserExeResult userExeResult = new UserExeResult();
            userExeResult.setInput(inputList.get(i));
            userExeResult.setOutput(exeOutputList.get(i));
            userExeResult.setExeOutput(expOutputList.get(i));
            userExeResultList.add(userExeResult);
        }
        if(userExeResultList.isEmpty()){
            System.out.println("userExeResultList is null");
        }
        boolean pass = true;
        for (int i = 0; i < exeOutputList.size(); i++) {
            if (!exeOutputList.get(i).equals(expOutputList.get(i))) {
                pass = false;
                break;
            }
        }
        if (!pass) {
            return UserQuestionResultVO.fail(Constants.FALSE, JudgeConstants.ERROR_ANSWER, userExeResultList, JudgeConstants.ERROR_SCORE);
        }
        // 测试用例都通过才会进行时空间的对比
        // 比对时间 空间限制
        if (sandBoxExecuteResult.getUseTime() > judgeSubmitDTO.getTimeLimit()) {

            return UserQuestionResultVO.fail(Constants.FALSE, JudgeConstants.OUT_OF_TIME, userExeResultList, JudgeConstants.ERROR_SCORE);

        }
        if (sandBoxExecuteResult.getUseMemory() > judgeSubmitDTO.getSpaceLimit()) {

            return UserQuestionResultVO.fail(Constants.FALSE, JudgeConstants.OUT_OF_MEMORY, userExeResultList, JudgeConstants.ERROR_SCORE);

        }
        // 测试用例都通过 且 时空间符合条件 才会赋值正确
        Integer realScore = JudgeConstants.DEFAULT_SCORE * judgeSubmitDTO.getDifficulty(); // 根据难度判断分数
        return UserQuestionResultVO.success(Constants.TRUE, JudgeConstants.PASS, userExeResultList, realScore);

    }

    private void saveUserSubmit(JudgeSubmitDTO judgeSubmitDTO, UserQuestionResultVO userQuestionResultVO) {
        UserSubmit userSubmit = new UserSubmit();
        BeanUtil.copyProperties(judgeSubmitDTO, userSubmit);
        BeanUtil.copyProperties(userQuestionResultVO, userSubmit);
        userSubmit.setCreateBy(judgeSubmitDTO.getUserId());

        List<UserExeResult> userExeResultList = userQuestionResultVO.getUserExeResultList();
        userSubmit.setCaseJudgeRes(JSON.toJSONString(userExeResultList));
        userSubmitMapper.delete(new LambdaQueryWrapper<UserSubmit>()
                .eq(UserSubmit::getQuestionId, judgeSubmitDTO.getQuestionId())
                .eq(UserSubmit::getUserId, judgeSubmitDTO.getUserId())
                .isNull(judgeSubmitDTO.getExamId() == null, UserSubmit::getExamId) // 生成examId == null的条件
                .eq(judgeSubmitDTO.getExamId() != null, UserSubmit::getExamId, judgeSubmitDTO.getExamId())
        );
        // 只存最后的 可以设计成历史记录都保存
        userSubmitMapper.insert(userSubmit);
    }
}
